﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;
using WebAppMatrix.Extensions;
using System.Security.Cryptography;

namespace WebAppMatrix.Security
{
    public class Security : IHttpModule
    {
        #region IHttpModule 成员

        public void Dispose()
        {

        }

        public void Init(HttpApplication context)
        {
            context.AuthenticateRequest += ContextAuthenticateRequest;
        }

        #endregion

        /// <summary>
        /// 保存在客户端的认证信息Cookie名称
        /// </summary>
        public static string FormsAuthCookieName
        {
            get { return FormsAuthentication.FormsCookieName; }
        }

        /// <summary>
        /// 用来分割用户票据中用户信息的分隔符
        /// </summary>
        public static string AUTH_TKT_USERDATA_DELIMITER
        {
            get { return "-|-"; }
        }

        public static string SecurityValidationKey
        {
            get { return MatrixManager.Settings.SecurityValidationKey; }
        }

        /// <summary>
        /// 认证请求
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void ContextAuthenticateRequest(object sender, EventArgs e)
        {
            //得到当前的HttpContext
            var context = ((HttpApplication)sender).Context;
            //得到FormsAuth的Cookie信息
            HttpCookie authCookie = context.Request.Cookies[FormsAuthCookieName];

            if (authCookie != null)
            {
                FormsAuthenticationTicket authTicket = null;
                try
                {
                    authTicket = FormsAuthentication.Decrypt(authCookie.Value);
                }
                catch (Exception ex)
                {

                }

                if (authTicket != null && !string.IsNullOrWhiteSpace(authTicket.UserData))
                {
                    int delimiter = authTicket.UserData.IndexOf(AUTH_TKT_USERDATA_DELIMITER);
                    if (delimiter != -1)
                    {
                        string securityValidationKey = authTicket.UserData.Substring(0, delimiter).Trim();

                        if (securityValidationKey == SecurityValidationKey)
                        {
                            MatrixIdentity identity = new MatrixIdentity(authTicket.Name, true);
                            MatrixPrincipal principal = new MatrixPrincipal(identity);

                            context.User = principal;
                            return;
                        }
                    }
                }
            }
            //创建一个空的未认证用户信息
            MatrixIdentity unauthIdentity = new MatrixIdentity(string.Empty, false);
            MatrixPrincipal unauthPrincipal = new MatrixPrincipal(unauthIdentity);
            context.User = unauthPrincipal;
        }

        /// <summary>
        /// 注销登陆
        /// </summary>
        public static void SignOut()
        {
            // using a custom cookie name based on the current blog instance.
            HttpCookie cookie = new HttpCookie(FormsAuthCookieName, string.Empty);
            cookie.Expires = DateTime.Now.AddYears(-3);
            HttpContext.Current.Response.Cookies.Add(cookie);
        }

        /// <summary>
        /// 认证用户
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="rememberMe"></param>
        /// <returns></returns>
        public static bool AuthenticateUser(string username, string password, bool rememberMe)
        {
            string un = (username ?? string.Empty).Trim();
            string pw = (password ?? string.Empty).Trim();

            if (!string.IsNullOrWhiteSpace(un) && !string.IsNullOrWhiteSpace(pw))
            {
                bool isValidated = Membership.ValidateUser(un, pw);

                if (isValidated)
                {
                    HttpContext context = HttpContext.Current;
                    DateTime expirationDate = DateTime.Now.Add(FormsAuthentication.Timeout);

                    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                        1,
                        un,
                        DateTime.Now,
                        expirationDate,
                        rememberMe,
                        string.Format("{0}{1}", SecurityValidationKey, AUTH_TKT_USERDATA_DELIMITER),
                        FormsAuthentication.FormsCookiePath
                    );

                    string encryptedTicket = FormsAuthentication.Encrypt(ticket);

                    //保存客户端认证的cookie
                    HttpCookie cookie = new HttpCookie(FormsAuthCookieName, encryptedTicket);
                    cookie.Expires = rememberMe ? expirationDate : DateTime.MinValue;
                    cookie.HttpOnly = true;
                    context.Response.Cookies.Set(cookie);

                    string returnUrl = context.Request.QueryString["returnUrl"];

                    // ignore Return URLs not beginning with a forward slash, such as remote sites.
                    if (string.IsNullOrWhiteSpace(returnUrl) || !returnUrl.StartsWith("/"))
                        returnUrl = null;

                    if (!string.IsNullOrWhiteSpace(returnUrl))
                    {
                        context.Response.Redirect(returnUrl);
                    }
                    else
                    {
                        context.Response.Redirect(FormsAuthentication.DefaultUrl);
                    }

                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 使用SHA256对密码进行加密
        /// </summary>
        /// <param name="password">密码明文</param>
        /// <returns></returns>
        public static string HashPassword(string password)
        {
            var data = Encoding.UTF8.GetBytes(password);
            using (HashAlgorithm sha = new SHA256Managed())
            {
                sha.TransformFinalBlock(data, 0, data.Length);
                return Convert.ToBase64String(sha.Hash);
            }
        }

        /// <summary>
        /// 跳转到登陆页面
        /// </summary>
        public static void RedirectToLoginPage()
        {
            HttpContext.Current.Response.Redirect(FormsAuthentication.LoginUrl);
        }
    }
}
